package com.kuang.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kuang.bascic.Myexception.BusinessException;
import com.kuang.bascic.utils.AjaxResult;
import com.kuang.bascic.utils.HttpClientUtils;
import com.kuang.user.constant.WxConstants;
import com.kuang.user.domian.LoginInfo;
import com.kuang.user.domian.User;
import com.kuang.user.domian.WxUser;
import com.kuang.user.mapper.UserMapper;
import com.kuang.user.mapper.WxUserMapper;
import io.netty.util.internal.StringUtil;
import netscape.javascript.JSObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WxLoginServiceImpl implements WxLoginService {

    @Value("${jwt.rsa.pri}")// SPEL表达式读取配置文件中的值
    private String jwtRsaPrivate;
    @Autowired
    private WxUserMapper wxUserMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private LoginService loginServicel;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public AjaxResult wxLogin(Map<String, String> map) {
        //{code=031FUGml2Xqnt94jJrll2gCNLI1FUGmr, state=STATE}
        String code = map.get("code");
        // "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        String url= WxConstants.GET_ACK_URL.replace("APPID",WxConstants.APPID)
                .replace("SECRET",WxConstants.SECRET).
                replace("CODE",code);
        String res = HttpClientUtils.httpGet(url);
        /**；·
         * {
         * 返回结果
         * 	"access_token": "58_jYLcizP8fQf3GEDN2xcvMAPUfGxkqNHmUezrnpqdzO4w3V4sXTiQuCQD7vUj264WMJGr0jqKMrYGRdkyD9-cRt0eDeXwDGfCH89TCM22KSs",
         * 	"expires_in": 7200,
         * 	"refresh_token": "58_wpuM8P0oOV4Ffnu45lnGBtfJqzxa53Ex53M7czxjpZoq6x1itvqRO-gjVOomZNinjlXOvglYISK1debvrjIcWiZ0-SAqo-3RLOfAFclz1lw",
         * 	"openid": "oa9wA05Aqpiq4VQp-MWsno7NNCSM",
         * 	"scope": "snsapi_login",
         * 	"unionid": "ovnCWwy309Dujylpbk-demFhmjCI"
         *
         * 	解释：
         * access_token 	接口调用凭证
         * expires_in 	access_token接口调用凭证超时时间，单位（秒）
         * refresh_token 	用户刷新access_token
         * openid 	授权用户唯一标识
         * scope 	用户授权的作用域，使用逗号（,）分隔
         * unionid 	当且仅当该网站应用已获得该用户的 userinfo 授权时，才会出现该字段。
         * 返回的json数据格式  期望将其转换为map  通过key获取value
         * 
         * alibaba  有个fastJSON 工具可以转换json数据格式为类似map一样看k，v  取值
         *
         * }
         */
        JSONObject jsonObject = JSON.parseObject(res);
        Object access_token = jsonObject.get("access_token");
        Object openid = jsonObject.get("openid");
        //2. 我们如何和数据相结合
        // 拿到了用户唯一标识去数据库查询用户信息
        WxUser wxUser = wxUserMapper.selectByOpenid(openid);
        System.out.println(wxUser);
        // 判断是否拿到了 拿到了是老用户 没拿到是新用户
        if (wxUser!=null){
            // 通过 外键 user_id查询用户 获取到了用户
            User user = userService.selectDepartmentById(wxUser.getUser_id());
            // 通过user查询 存放登录信息表
            LoginInfo loginInfo = loginServicel.selectDepartmentById(user.getLogininfo_id());
            // 得到登录信息表 实现免密登录 免密登录新老用户都用 封装工具类
            AjaxResult ajaxResult = NoPwdLogin(loginInfo,wxUser);
            return ajaxResult;
        }else {
            // 没拿到 说明是新用户  让他去绑定
            // 给前端发送提示绑定信息加上接口凭证和用户id 到url中 方便获取微信个人信息
            // 这里是微信扫码登陆后直接从这里给到跳转信息
            String Url="binder.html?access_token="+access_token+"&"+"openid="+openid+"";
            return AjaxResult.me().setMessage("BIND").setResultObj(Url);
        }

    }

    @Override
    @Transactional
    public AjaxResult bind(Map<String, String> map) {
        /**
         * 	// 绑定参数 里加上微信个人信息
         * "phone":this.phoneUserForm.phone,
         * "code":this.phoneUserForm.verifyCode,
         * "codetype":this.phoneUserForm.codetype,
         * "ACCESS_TOKEN": Userdata.ACCESS_TOKEN,
         * "OPENID":Userdata.OPENID,
         */
        System.out.println(map);
        String phone = map.get("phone");
        String code = map.get("code");
        String codetype = map.get("codetype");
        String ACCESS_TOKEN = map.get("access_token");
        String OPENID = map.get("openid");
        //绑定 需要做的事情
        //phone：
        //code：
        /**验证手机号和验证码
         * 2.查询user表里面 当前的手机号是否注册过
         *      注册过：生成一个wxuser 和一个已经存储在user对象关联
         *      没有注册：生成一个user（和logininfo）生成一个wxuser 关联
         *  3 .免密登录
         */
        // 验证手机号和验证码
        // 判是否为空
        //"phone"
        //"code":
        // 1.验证是手机号和验证码
        try {
            verifyData(map);
        } catch (BusinessException e) {
            return AjaxResult.me().setMessage(e.getMessage());
        }
        // 2.查询user表里面 当前的手机号是否注册过没有注册：生成一个user（和logininfo）生成一个wxuser 关联
//        User userPhone = userService.selectUserByPhone(map.get("phone"));
            //生成一个user对象（和logininfo）生成一个wxuser 关联
            // 发送请求获取微信个人信息  这里跨方法了 因为是单例模式只创建一个对象 存在线程不安全
        String url=WxConstants.GET_USER_URL.
          replace("ACCESS_TOKEN",ACCESS_TOKEN).
          replace("OPENID",OPENID);
        /**
         * {
         * 	"openid": "oa9wA05Aqpiq4VQp-MWsno7NNCSM",
         * 	"nickname": "不讲wood",
         * 	"sex": 0,
         * 	"language": "",
         * 	"city": "",
         * 	"province": "",
         * 	"country": "",
         * 	"headimgurl": "https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTL1NTmO15o4bpMLoBLSD2yicS43aeNAVicW1m4a35EAxz84cw5sZlrHM3EJnNqe4wCvTD17TVUrqGibg\/132",
         * 	"privilege": [],
         * 	"unionid": "ovnCWwy309Dujylpbk-demFhmjCI"
         * }
         */
        // 这里拿到了微信的个人信息 绑定个人信息到wxuser  关联user 关联login——info
        // 得到的微信个人信息json数据格式一定要格式化
        String UserData = HttpClientUtils.httpGet(url);
        WxUser wxUser = new WxUser();
        // 格式化微信用户数据
        JSONObject parseDate = JSON.parseObject(UserData);
        wxUser.setNickname(parseDate.getString("nickname"));
        wxUser.setSex(parseDate.getInteger("sex"));
        String Address=parseDate.getString("country")+parseDate.getString("province")+parseDate.getString("city");
        wxUser.setAddress(Address);
        wxUser.setUnionid(parseDate.getString("unionid"));
        wxUser.setOpenid(parseDate.getString("openid"));
        wxUser.setHeadimgurl(parseDate.getString("headimgurl"));
//        private Long user_id;
        //生成一个wxuser对象绑定上
        User user = userService.selectUserByPhone(phone);
        LoginInfo loginInfo = null;
        if (user==null){
            //说明用户未注册  把用户存进user和logininfo里面
            // 先给用户注册user表和logininfo表
            // 如果为空就给他赋空值
           user = new User();
            user.setPhone(phone);
            user.setUsername(parseDate.getString("nickname"));
            user.setState(1);
            user.setCreatetime(new Date());
            user.setHeadImg(parseDate.getString("headimgurl"));
//            private Long logininfo_id;
            loginInfo = new LoginInfo();
            BeanUtils.copyProperties(user,loginInfo);
            loginInfo.setDisable(1);
            loginInfo.setType(1);
            // 保存进数据库
            loginServicel.addDepartment(loginInfo);
            user.setLogininfo_id(loginInfo.getId());
            userService.addDepartment(user);
        }else{
            // 表示用户已经在系统里面 已经注册
           loginInfo = loginServicel.selectDepartmentById(user.getLogininfo_id());
            //查到了登录信息
        }
        // 与wxUser建立连接
        wxUser.setUser_id(user.getId());
        // 存入微信用户数据库
        wxUserMapper.addDepartment(wxUser);
        // 开启免密登录
        return NoPwdLogin(loginInfo,wxUser);

    }

    private void verifyData(Map<String, String> map) {
        String codeInfo  = (String) redisTemplate.opsForValue().get(map.get("phone") + ":" + map.get("codetype"));
        if (codeInfo==null) {
            throw new BusinessException("验证码有误");
        }else {
            // 点击了去和redis做对比
            // 截取出来的就是redis里面的验证码
            String code1 = codeInfo.split(":")[0];
            if (!map.get("code").equals(code1)) {
                // 抛了后面捕获
                throw new BusinessException("验证码错误");
            }
    }
    }
    private AjaxResult NoPwdLogin(LoginInfo loginInfo,WxUser user) {
        // 生成一个随机token
        String token = UUID.randomUUID().toString();
        // 将信息加入到redis
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        // 将数据返回给前端  这里正好使用上我们制作的工具类
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("loginInfo",loginInfo);
        map.put("resource",user.getHeadimgurl());
        map.put("nickname",user.getNickname());
        // 清空敏感数据
        loginInfo.setPassword("");
        loginInfo.setSalt("");
        // 返回给前端 token 和 已经清空敏感登录信息
        return  AjaxResult.me().setResultObj(map);
    }
}
